package core;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

import util.DrawGraph;

public class Frame extends JFrame{

	/**
	 * Generated UID
	 */
	private static final long serialVersionUID = -6069462403474851173L;

	static final int boxWidth = 50;
	static final int boxHeight = 50;
	private static final String DEFAULT_TITLE = "P2P node";
	private boolean isServent = false;
	Servent myServent;
	JPanel rootPanel;
	JTextArea log;
	JButton startStop;

	JButton visual;
	private boolean enable_visual = false;
	

	JComboBox whoami;

	Canvas can;
	BufferedImage bgImg;

	int width;
	int height;
	
	DrawGraph graphDrawer;

	public Frame() {
		super(DEFAULT_TITLE);

		setDefaultCloseOperation(EXIT_ON_CLOSE);

		setVisible(true);

		rootPanel = new JPanel();

		JPanel actionsPanel = new JPanel();
		actionsPanel.setLayout(new BoxLayout(actionsPanel, BoxLayout.Y_AXIS));
		log = new JTextArea(30, 30);
		JScrollPane logPane = new JScrollPane(log);

		String[] serventNames = {"A","B","C","D"};
		whoami = new JComboBox(serventNames);
//		whoami.setPreferredSize(new Dimension(boxWidth, boxHeight));

		JLabel whoamiExplain = new JLabel("Choose which node this is");

//		Button to start and stop the servent thread
		startStop = new JButton("Start");
//		button.setPreferredSize(new Dimension(boxWidth, boxHeight));
		visual = new JButton("Visualization");

		add(rootPanel);
		rootPanel.add(logPane);
		rootPanel.add(actionsPanel);

		actionsPanel.add(whoamiExplain);
		actionsPanel.add(whoami);	
		actionsPanel.add(startStop);
		actionsPanel.add(visual);

		//Want to set to the same size as log but it returns [0,0]
		width = 300;
		height = 480;

		can = new Canvas();
		can.setBackground(Color.black);
//		rootPanel.add(can);
//		can.createBufferStrategy(2);
//		can.setSize(width,height);

		//Create a black background image that are used later
		bgImg = new BufferedImage( width,height, BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = (Graphics2D) bgImg.getGraphics();
		g.setColor(Color.black);
		g.fillRect(0, 0, width,height);
		g.dispose();
		//End create image

		setResizable(false);
		pack();
		
		graphDrawer = new DrawGraph(width, height);
		//For testing
		graphDrawer.no_nodes=4;
		graphDrawer.nodes = serventNames.clone();
	}



	public void run() {
		while(true) {
			if(enable_visual) {
				BufferStrategy bf = can.getBufferStrategy();
				Graphics2D g = null;
				g = (Graphics2D) bf.getDrawGraphics();
				g.drawImage(bgImg,0,0,rootPanel);
				//Draw visualizations
				graphDrawer.draw(g);
				
				//End draw visualizations
				g.dispose();
				bf.show();
				try {
					Thread.sleep(50);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			} else {
				pack();
			}
			try {
				Thread.sleep(50);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public synchronized void writeToLog(String name,String msg) {
		log.insert(name+": "+msg+"\n", 0);
		log.setCaretPosition(0); // MIND = BLOWN
	}
	
	public synchronized void updateLastMsg(String from) {
		System.out.println("last msg from updates to: " + from);
		if(from != null)
			graphDrawer.lastMsgFrom = from;
	}

	/**
	 * Create a Frame and set everything. Would like to have all the setting in a constructor but
	 * its hard to fix the action listener.
	 * @param args
	 */
	public static void main(String[] args) {

		final Frame foo = new Frame();

		foo.startStop.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {

				if(!foo.isServent()) {
					switch(foo.whoami.getSelectedIndex()) {
					case 0: {
						foo.myServent = new Servent(1111, 2222,"A", foo); 
						foo.setTitle("Node A");
						break;
					}
					case 1: {
						foo.myServent = new Servent(2222, 3333,"B", foo); 
						foo.setTitle("Node B");
						break;
					}
					case 2: {
						foo.myServent = new Servent(3333, 4444,"C", foo); 
						foo.setTitle("Node C");
						break;
					}
					case 3: {
						foo.myServent = new Servent(4444, 1111,"D", foo); 
						foo.setTitle("Node D");
						break;
					}
					default: System.err.println("Frame: Match error"); break;
					} 
					foo.isServent(true);
					foo.startStop.setText("Stop");
					foo.myServent.start();
					foo.myServent.setRunning(true);
				} else {
					foo.stop();
					foo.setTitle(DEFAULT_TITLE);
				}

			}
		});
		foo.visual.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent arg0) {
				if(foo.enable_visual){
					foo.rootPanel.remove(foo.can);
					foo.validate();
					foo.enable_visual = false;
				} else {
					
					foo.rootPanel.add(foo.can);
					foo.can.createBufferStrategy(2);
					foo.can.setSize(foo.width,foo.height);
					foo.pack();
					//must be set last so we actually have a buffer strategy
					foo.enable_visual = true;
				}
			}
		});

		foo.run();
	}
	
	public void stop() {
		myServent.setRunning(false);
		isServent(false);
		startStop.setText("Start");
	}
	
	private synchronized void isServent(boolean isServent) {
		this.isServent = isServent;
	}
	
	private synchronized boolean isServent() {
		return isServent;
	}

}
